package edu.usm.predatorwars.webservice;

import java.util.UUID;

import javax.ws.rs.core.MediaType;

import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.ClientResponse.Status;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;
import com.sun.jersey.api.json.JSONConfiguration;

import edu.predatorwars.shared.models.Creature;
import edu.predatorwars.shared.models.GameListPayload;
import edu.predatorwars.shared.models.Move;
import edu.predatorwars.shared.models.MovementPayload;
import edu.predatorwars.shared.models.Player;
import edu.predatorwars.shared.models.PlayerGamePayload;
import edu.predatorwars.shared.models.SelectCharacterPayload;
import edu.usm.predatorwars.GameHostResourceClient;

/**
 * Web service client to the Game Host
 */
public class GameHostClient implements GameHostResourceClient {
	private static final String GAME_HOST_CONTEXT = "/predatorwars";
	private static final String CREATE_GAME_RESOURCE = GAME_HOST_CONTEXT + "/creategame";
	private static final String JOIN_GAME_RESOURCE = GAME_HOST_CONTEXT + "/joingame";
	private static final String QUIT_GAME_RESOURCE = GAME_HOST_CONTEXT + "/quitgame";
	private static final String SELECT_CHARACTER_RESOURCE = GAME_HOST_CONTEXT + "/selectcharacter";
	private static final String MOVE_RESOURCE = GAME_HOST_CONTEXT + "/move";
	private static final String REFRESH_LIST_RESOURCE = GAME_HOST_CONTEXT + "/refreshlist";
	private static final String IP_RESOURCE = GAME_HOST_CONTEXT + "/ip";
	private final String hostname;
	private final Client client;
	
	public GameHostClient(String hostname) {
		this.hostname = hostname;
		ClientConfig clientConfig = new DefaultClientConfig();
		clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
		client = Client.create(clientConfig);
	}
	
	public Boolean createGame(Player joiningPlayer) {
		ClientResponse response = postResource(CREATE_GAME_RESOURCE, joiningPlayer);
		System.out.println(response);
		if (!requestSuccess(response)) {
			return null;
		}
		return response.getEntity(Boolean.class);
	}

	private boolean requestSuccess(ClientResponse response) {
		return response.getClientResponseStatus().equals(Status.OK);
	}

	private ClientResponse postResource(String resourcePath, Object requestResource) {
		WebResource resource = client.resource(hostname + resourcePath);System.out.println(requestResource);
		ClientResponse response = resource.type(MediaType.APPLICATION_JSON).post(ClientResponse.class, requestResource);
		return response;
	}
	
	public boolean joinGame(Player joiningPlayer, UUID gameId) {
		PlayerGamePayload payload = new PlayerGamePayload(joiningPlayer, gameId);
		ClientResponse response = postResource(JOIN_GAME_RESOURCE, payload);
		return response.getClientResponseStatus().equals(Status.OK);
	}
	
	public boolean quitGame(Player player, UUID gameId) {
		PlayerGamePayload payload = new PlayerGamePayload(player, gameId);
		ClientResponse response = postResource(QUIT_GAME_RESOURCE, payload);
		return response.getClientResponseStatus().equals(Status.OK);
	}
	
	public boolean selectCharacter(Player player, Creature creature, UUID gameId) {
		SelectCharacterPayload payload = new SelectCharacterPayload(player, creature, gameId);
		ClientResponse response = postResource(SELECT_CHARACTER_RESOURCE, payload);
		return response.getClientResponseStatus().equals(Status.OK);
	}
	
	public boolean makeMovement(Player player, Move move, UUID gameId, UUID snapshot) {
		MovementPayload payload = new MovementPayload(player, move, gameId, snapshot);
		ClientResponse response = postResource(MOVE_RESOURCE, payload);
		return response.getClientResponseStatus().equals(Status.OK);
	}
	
	public GameListPayload refreshGameList() {
		ClientResponse response = getResource(REFRESH_LIST_RESOURCE);
		if (!requestSuccess(response)) {
			return null;
		}
		
		return response.getEntity(GameListPayload.class);
	}

	private ClientResponse getResource(String resourcePath) {
		WebResource resource = client.resource(hostname + resourcePath);
		ClientResponse response = resource.type(MediaType.APPLICATION_JSON).get(ClientResponse.class);
		return response;

	}
	
	public String getIpAddress() {
		ClientResponse response = getResource(IP_RESOURCE);
		if (!requestSuccess(response)) {
			return null;
		}
		
		return response.getEntity(String.class);
	}
}
